from flask import Blueprint, jsonify, request, render_template
from models.entity.device import Device
import json
from models.entity.device_type import DeviceType
from models.entity.device_group import DeviceGroup
from models.entity.district_with_device import DistrictWithDevice
from models.entity.device_info import DeviceInfo
from models.entity.point import Point
from models.entity.sensor import Sensor
from models.entity.device_with_sensor import DeviceWithSensor
from models.entity.district import District
from models.entity.facility import Facility
from models.entity.facility_with_device import FacilityWithDevice
import datetime
from utils.result import result

mod = Blueprint("core_device", __name__, url_prefix="/core/device", template_folder="templates", static_folder="static")

@mod.route('/', methods=['GET'])
def device_index():
    return render_template("/admin/core/device_index.html")

@mod.route('/add/', methods=['GET', 'POST'])
def add_device():
    """增加设备"""
    """
    {
    "name":"ddddd10",
    "code":"d2ddd5",
    "description":"22222",
    "district_id":1
    "dis_order":3,
    "device_type_id":4,
    "device_group_id":4,
    "parent_id":0,
    "status":1,
    "lon":152,
    "lat":125,
    "sensors":[sensor_id_1,sensor_id_2,...],
    "valid_time":365    // 有效天数,单位是天
    }

    dict {'name': '123123312', 'description': '', 'lat': 37.813576, 'valid_time': 0, 'status': 1,
    'code': '123123123', 'device_group_id': 1, 'lng': 112.58798, 'start_time': '2018-09-26',
    'device_type_id': 1, 'district_id': 3}

    """
    if request.method == 'POST':
        tmp = {}
        data = []
        dict = json.loads(request.data.decode("utf-8"))
        print('dict', dict)
        if 'district_id' in dict:
            tmp['district_id'] = dict.pop('district_id')
        device = Device()
        try:
            device.from_dict(dict)
        except RuntimeError as e:
            return result(success=0,error_code=-1,error_msg=e)
        if not DeviceType.get_device_type_by_id(dict['device_type_id']):
            return result(success=0,error_code=-2,error_msg='设备类型不存在')
        if not DeviceGroup.get_device_group_by_id(dict['device_group_id']):
            return result(success=0,error_code=-2,error_msg='设备分组不存在')
        if Device.get_device_by_name(dict['name']):
            return result(success=0,error_code=-2,error_msg='名称已经存在')
        if Device.get_device_by_code(dict['code']):
            return result(success=0,error_code=-3,error_msg='设备编码已存在')
        if device.save():
            # 建立分区和设备的中间表联系
            connectorA = DistrictWithDevice()
            connectorA.device_id = device.id
            connectorA.district_id = tmp['district_id']
            if connectorA.save() is False:
                print("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")
                return result(success=0,error_code=-3,error_msg='未知错误')
            # # 建立设备与传感器的中间表关联
            # for item in sensors:
            #     sensor = Sensor.get_sensor_by_id(item)
            #     if sensor is None:
            #         tmp['success'] = 0
            #         tmp['error_code'] = -4
            #         tmp['error_msg'] = "unknown error"
            #         tmp['data'] = data
            #         return jsonify(tmp)
            #     connectorB = DeviceWithSensor()
            #     connectorB.device_id = device.id
            #     connectorB.sensor_id = sensor.id
            #     if connectorB.save() is False:
            #         print("bbbbbbbbbbbbbbbbbbbbbbbbbbbbb")
            #         tmp['success'] = 0
            #         tmp['error_code'] = -4
            #         tmp['error_msg'] = "unknown error"
            #         tmp['data'] = data
            #         return jsonify(tmp)
            return result(data=[device.to_dict()])
        else:
            return result(success=0,error_code=-4,error_msg="未知错误")


@mod.route('/edit/', methods=['GET', 'POST'])
def edit_device():
    """编辑设备"""
    """
    {
    "id":2,
    "name":"ddddd10",
    "code":"d2ddd5",
    "description":"22222",
    "dis_order":3,
    "device_type_id":4,
    "ParentId":0,
    "status":1,
    "lon":152,
    "lat":125,
    "district_id":1,
    "sensors":[sensor_id_1,sensor_id_2, ...],
    "valid_time":365    // 设备有效时间,单位是天
    }

    111dict {'description': '', 'icon': None, 'lng': 112.639, 'district_id': 2,
    'code': '3123', 'data_type': 3, 'level': 1, 'id': 8, 'valid_time': 123,
    'device_type_id': 1, 'sensors': [], 'dis_order': 0, 'name': '12', 'parent_id': 0,
     'status': 1, 'lat': 37.8478, 'device_group_id': 2, 'start_time': '2018-09-26'

    """
    if request.method == 'POST':
        tmp = {}
        data = []
        dict = json.loads(request.data.decode("utf-8"))
        print('111dict', dict)
        device = Device().get_entity_by_id(dict['id'])
        try:
            start_time = datetime.datetime.strptime(dict['start_time'], '%Y-%m-%d')
        except:
            return result(success=0,error_code=-4,error_msg="开始时间格式错误")
        else:
            start_time = None
        if device.name != dict['name'] and Device.query.filter_by(name=dict['name']).first():
            return result(success=0,error_code=-4,error_msg="设备名称已存在")
        if device.code != dict['code'] and Device.query.filter_by(code=dict['name']).first():
            return result(success=0,error_code=-4,error_msg="设备编码已存在")
        if not DeviceType.get_device_type_by_id(dict['device_type_id']):
            return result(success=0,error_code=-4,error_msg="设备类型不存在")
        if not DeviceGroup.get_device_group_by_id(dict['device_group_id']):
            return result(success=0,error_code=-4,error_msg="设备分组不存在")
        # set_old_sensors = set(device.get_dic()["sensors"])
        # set_sensors = set(sensors)
        # if set_sensors != set_old_sensors:
        #     # 如果传感器被修改了
        #     # 删除原有设备和传感器的中间表
        #     for item in set_old_sensors:
        #         if item.delete() is False:
        #             tmp['success'] = 0
        #             tmp["error_code"] = -5
        #             tmp['error_msg'] = "unknown error"
        #             tmp['data'] = data
        #             return jsonify(tmp)
            # 建立新的设备和传感器的中间表
            # for t_item in set_sensors:
            #     connector = DeviceWithSensor()
            #     connector.device_id = device.id
            #     connector.sensor_id = t_item.id
            #     if connector.save() is False:
            #         tmp['success'] = 0
            #         tmp['error_code'] = -6
            #         tmp['error_msg'] = "unknown error"
            #         tmp['data'] = data
            #         return jsonify(t

        try:
            sensors = dict.get('sensors')
            print('sensors', sensors)
            device.from_dict(dict)
        except RuntimeError as e:
            return result(success=0, error_code=-1, error_msg='格式错误')
        print(22222)
        if device.save() is True:
            # 处理分区和设备的中间表联系
            # 删除旧的关系
            old_connector = DistrictWithDevice.query.filter_by(device_id=device.id).first()
            if not old_connector is None:
                if old_connector.delete() is False:
                    return result(success=0, error_code=-1, error_msg='未知错误')
            # 新建关系
            connector = DistrictWithDevice()
            connector.device_id = device.id
            connector.district_id = dict['district_id']
            if connector.save() is False:
                return result(success=0, error_code=-1, error_msg='未知错误')
            #return result(success=1)  # 先不返回
            ###
            deviceWithsensor = DeviceWithSensor.query.filter_by(device_id=device.id).first()
            if not deviceWithsensor is None:
                if deviceWithsensor.delete() is False:
                    return result(success=0, error_code=-1, error_msg='未知错误')
            # 新建关系
            for i in sensors:
                connector2 = DeviceWithSensor()
                connector2.device_id = device.id
                connector2.sensor_id = i
                if connector2.save() is False:
                    return result(success=0, error_code=-1, error_msg='未知错误')
            return result(success=1)
        else:
            return result(success=0, error_code=-1, error_msg='未知错误')


@mod.route('/del/', methods=['GET', 'POST'])
def del_device():
    """删除设备分组分类"""
    """
    {
    "id":2
    }
    """
    if request.method == 'POST':
        tmp = {}
        data = []
        dict = json.loads(request.data.decode("utf-8"))
        print('dict', dict)
        id = dict['id']
        if not Device.query.filter_by(id=id).first():
            return result(success=0, error_code=-1, error_msg='此设备不存在')
        device = Device.query.filter_by(id=id).first()
        # 检查这个设备下是否还有子设备
        if Device.query.filter_by(parent_id=device.id).first():
            return result(success=0, error_code=-1, error_msg='此设备存在子设备')
        # 检查这个设备下是否有传感器
        if len(Sensor.get_sensors_by_device_id(device.id)) != 0:
            return result(success=0, error_code=-1, error_msg='此设备下依然存在传感器')
        # 删除这个device关联的中间表记录
        for item in DistrictWithDevice.query.filter_by(device_id=device.id).all():
            if item.delete() is False:
                return result(success=0, error_code=-1, error_msg='未知错误')
        for item in DeviceWithSensor.query.filter_by(device_id=device.id).all():
            if item.delete() is False:
                return result(success=0, error_code=-2, error_msg='未知错误')
        # 删除这个device关联的device_info
        device_info = DeviceInfo.query.filter_by(device_id=device.id)
        if device_info.delete() is False:
            return result(success=0, error_code=-3, error_msg='未知错误')
        # 下面开始删除
        if device.delete():
            return result(success=1)
        else:
            return result(success=0, error_code=-4, error_msg='存在子节点，请先删除子节点')

@mod.route("/get_tree/", methods=["GET", "POST"])
def get_tree_json():
    """返回模块列表，这个方法可能压根就用不上,用post"""
    # 请求数据格式：无
    device_root = Device.query.filter_by(parent_id=0).all()  # 得到所有的根节点
    t_list = []
    for item in device_root:
        t_dict = item.to_dict()
        t_dict["children"] = item.get_tree_by_pid(item.id)
        t_list.append(t_dict)
    return result(data=t_list)


@mod.route("/get_all/", methods=["GET", "POST"])
def get_all_interface():
    all_device = Device.get_device_all()
    rdic = {}
    rdic["data"] = []
    for item in all_device:
        rdic["data"].append(item.to_dict())
    return result(data=rdic['data'])


@mod.route("/get_all_by_district_id/", methods=["POST"])
def get_all_by_district():
    """
    根据分区id获取所有设备
    """
    # request: json
    # {
    #       "id":id    // 分区id
    # }
    try:
        data = json.loads(request.data.decode("utf-8"))
    except:
        return result(success=0, error_code=-1, error_msg='数据格式错误')
    if "id" in data:
        id = data["id"]
    else:
        return result(success= 0, error_code=-2, error_msg='数据格式错误')
    all_device = Device.get_devices_by_district_id(id)
    rdic = {}
    rdic["data"] = []
    for item in all_device:
        rdic["data"].append(item.to_dict())
    return result(data=rdic["data"])


@mod.route("/get_all_by_device_group_id/", methods=["POST"])
def get_device_all_by_device_group_id():
    """
    根据设备组id获取所有设备
    """
    # request: json
    # {
    #       "id":id    // 设备分组id
    # }
    try:
        data = json.loads(request.data.decode("utf-8"))
    except:
        return result(success=0, error_code=-1, error_msg='数据格式错误')
    if "id" in data:
        id = data["id"]
    else:
        return result(success=0, error_code=-1, error_msg='数据格式错误')
    all_device = Device.get_devices_by_group_id(id)
    rdic = {}
    rdic["data"] = []
    for item in all_device:
        rdic["data"].append(item.to_dict())
    return result(data=rdic["data"])


@mod.route("/get_all_by_device_type_id/", methods=["POST"])
def get_device_all_by_device_type_id():
    """
    根据设备类型id获取所有设备
    """
    # request: json
    # {
    #       "id":id    // 设备类型id
    # }
    try:
        data = json.loads(request.data.decode("utf-8"))
        print('data', data)
    except:
        return result(success=0,error_code=-1,error_msg='数据格式错误')
    if "id" in data:
        id = data["id"]
    all_device = Device.get_devices_by_type_id(id)
    rdic = {}
    rdic["data"] = []
    for item in all_device:
        rdic["data"].append(item.to_dict())
    return result(data=rdic["data"])


@mod.route("/search/", methods=["POST"])
def search_device():
    """
    模糊查询
    """
    # request: json
    # {
    #      "query_word": "lishimin"
    # }
    if request.method == 'POST':
        receive = request.get_data()
        data = json.loads(receive.decode("utf-8"))
        if 'query_word' in data:
            query_word = data['query_word']
        else:
            return result(success=0,error_code=-1,error_msg='数据格式错误')
        devices = Device.search(query_word)
        return result(success=1, error_code=None, error_msg=None, data=devices)

@mod.route("/check_device_life/",methods=["POST"])
def check_device_life():
    """
    监测设备是否过期的轮询接口
    """
    rdic={}
    rdic["have_overdue"]=0
    rdic["data"]=[]
    device_dict_list=[]
    all_device=Device.get_device_all()
    for item in all_device:
        if (item.start_time is not None) and  (datetime.datetime.now()>(item.start_time+datetime.timedelta(days=item.valid_time))):
            # 如果设备启动时间不为None并且设备已过期
            rdic["have_overdue"]=1
            device_dict_list.append(item.get_dic())
    rdic["data"]=device_dict_list
    return result(data=rdic["data"])






# 原来错误的版本, 改进之后正确的版本
@mod.route("/get_district_facility_device_tree/",methods=["GET", "POST"])
def get_district_facility_device_tree():

    # 获取分区和设施和设备的树

    def travel_tree(source): # 这里的source是分区列表 [<District_item 测试分区1>, <District_item 111>..6个],[<District_item 111>],[]
        # 将分区与设施放在一棵树下
        def in_travel_tree(id_num): # 原来方法
        # def in_travel_tree():
            sz=[]
            for obj in source:
                print('obj', obj)
                if isinstance(obj, District):
                    print('obj.pid:', obj.parent_id, 'in_id_num:', id_num)
                    if obj.parent_id == id_num:  # 0, 1
                        district_dic = obj.to_dict()   # dic 分区字典
                        facilities = Facility.get_facilities_by_district_id(obj.id)
                        devices = Device.get_devices_by_district_id(obj.id)
                        print("facilities", facilities, len(facilities))
                        print('devices',len(devices))
                        if len(District().get_list_by_pid(obj.id)) == 0:
                            print('该分区下的自分区长度:', len(District().get_list_by_pid(obj.id)))
                            if len(facilities) != 0:
                                # 如果该分区没有子分区并且本身具有设施
                                district_dic["children"]=[]
                                for item3 in facilities:
                                    # tdic=item.get_dic() # 原来的方法
                                    facility_dic = item3.to_dict() # tdic 设施字典
                                    facility_dic["children"]=[]
                                    all_first_level_devices = FacilityWithDevice.get_device_by_facility(item3.id)
                                    for item4 in all_first_level_devices:
                                        # tdic["children"].append(item.get_dic())
                                        facility_dic["children"].append(item4.to_dict())  # 我的方法
                                    district_dic["children"].append(facility_dic)
                            if len(devices)!=0:
                                # 如果该分区没有子分区并且本身具有设备
                                for item5 in devices:
                                    # dic["children"].append(item.get_dic()) # 原来的方法
                                    district_dic["children"].append(item5.to_dict())
                        else: # 该分区有子分区
                            print('else该分区下的子分区长度:', len(District().get_list_by_pid(obj.id)))
                            # districts = District().get_list_by_pid(obj.id)   # 获取4个子分区
                            # for item3 in districts:
                            #     district_dic["children"] = in_travel_tree(item3.parent_id)
                            #     pass


                            district_dic["children"]=in_travel_tree(obj.id)   # 原来的方法
                        sz.append(district_dic)
            return sz

        rlist=in_travel_tree(0) # 原来的方法
        # rlist = in_travel_tree(item2)
        print('rlist', rlist)
        return rlist

    districts = District.query.filter_by(depth=1).all()  # depth = 1是最顶级分区
    print('districts',len(districts))  # 12个顶层
    sources = []
    for item1 in districts:
        # all_children = District.query.filter(District.path.like(str(item1.id)+"%")).all()
        # print('all_children', all_children, len(all_children))
        # sources.append(all_children)
        t_list = []  #
        for t in District.query.all():
            if t.path.split(',')[0] == str(item1.id):
                t_list.append(t)
        print('t_list长度', len(t_list), t_list)
        sources.append(t_list)
    print('sources', sources,len(sources))

    rdic={}
    rdic["data"] = []
    # print('sources', sources)
    # sources [[<District_item 测试分区1>, <District_item 111>, <District_item cui1>, <District_item 124>, <District_item 2121>,
    # <District_item 123123qwe>], [<District_item 222>], [<District_item 333>], [<District_item 1212>], [<District_item 12>],
    # [<District_item 123123>], [<District_item 12123123>], [<District_item qwe>], [<District_item 1231qwe>], [<District_item qeqe>],
    # [<District_item 12312>], [<District_item qweqweqw>]]

    for item2 in sources:  # item2还是列表
        rdic["data"].append(travel_tree(item2)[0]) # 原来的方法
        print(11111)
        # rdic["data"].append(travel_tree(item2))  #
        # rdic["data"].append(travel_tree(item[0])[0]) # 我的方法
    return result(data=rdic["data"])



"""
@mod.route("/get_district_facility_device_tree/",methods=["GET", "POST"])
def get_district_facility_device_tree():

    # 获取分区和设施和设备的树, 分区不是已树的形式返回的版本,再改进

    def travel_tree(source): # 这里的source是item2,是实例分区
        # 将分区与设施放在一棵树下
        # def in_travel_tree(id_num): # 原来方法
        def in_travel_tree():
            sz=[]
            for obj in source:
                print('obj', obj)
                if isinstance(obj, District):
                    # if obj.parent_id == id_num:  # 0
                    dic = obj.to_dict()   # dic 分区字典
                    facilities = Facility.get_facilities_by_district_id(obj.id)
                    devices = Device.get_devices_by_district_id(obj.id)
                    print("facilities", facilities, len(facilities))
                    # if len(District().get_list_by_pid(obj.id)) == 0:
                    if District().get_entity_by_id(obj.id):
                        if len(facilities) != 0:
                            # 如果该分区没有子分区并且本身具有设施
                            dic["children"]=[]
                            for item in facilities:
                                # tdic=item.get_dic() # 原来的方法
                                tdic = item.to_dict() # tdic 设施字典
                                tdic["children"]=[]
                                all_first_level_devices = FacilityWithDevice.get_device_by_facility(item.id)
                                for item in all_first_level_devices:
                                    # tdic["children"].append(item.get_dic())
                                    tdic["children"].append(item.to_dict())  # 我的方法
                                dic["children"].append(tdic)
                        if len(devices)!=0:
                            # 如果该分区没有子分区并且本身具有设备
                            for item in devices:
                                # dic["children"].append(item.get_dic()) # 原来的方法
                                dic["children"].append(item.to_dict())
                    else: # 该分区有子分区
                        dic["children"]=in_travel_tree()
                    sz.append(dic)
            return sz

        # rlist=in_travel_tree(0) # 原来的方法
        rlist = in_travel_tree()
        print('rlist', rlist)
        return rlist

    districts = District.query.filter_by(depth=1).all()  # depth = 1是最顶级分区
    # print('districts', districts,len(districts)) 12个顶层
    sources= set()
    for item1 in districts:
        all_children = District.query.filter(District.path.like(str(item1.id)+','+"%")).all()
        print('all_children', all_children, len(all_children))
        for cc in all_children:

        # sources.append(all_children)
            sources.add(cc)
        sources.add(item1)
    rdic={}
    rdic["data"] = []
    # sources.append(item1)
    print(111)
    sources = list(sources)
    print('sources', sources, len(sources))
    print(2222)
    # sources [[<District_item qweqwe>, <District_item cui1>, <District_item 124>, <District_item 2121>,
    #  <District_item 123123qwe>], [], [], [], [], [], [], [], [], [], [], []]

    # sources 最新的 [<District_item 2121>, <District_item 123123qwe>, <District_item 111>, <District_item cui1>,
    #  <District_item 124>, <District_item 测试分区1>,17个全部拿到]
    rdic["data"].append(travel_tree(sources))
    # for item2 in sources:
    #     # rdic["data"].append(travel_tree(item)[0]) # 原来的方法
    #     print(11111)
    #     rdic["data"].append(travel_tree(item2))  #
        # rdic["data"].append(travel_tree(item[0])[0]) # 我的方法
    return result(data=rdic["data"][0])
"""

